package com.maptool.map;

import android.app.Activity;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;

import com.esri.arcgisruntime.geometry.AreaUnit;
import com.esri.arcgisruntime.geometry.AreaUnitId;
import com.esri.arcgisruntime.geometry.GeodeticCurveType;
import com.esri.arcgisruntime.geometry.Geometry;
import com.esri.arcgisruntime.geometry.GeometryEngine;
import com.esri.arcgisruntime.geometry.GeometryType;
import com.esri.arcgisruntime.geometry.ImmutablePart;
import com.esri.arcgisruntime.geometry.ImmutablePartCollection;
import com.esri.arcgisruntime.geometry.LinearUnit;
import com.esri.arcgisruntime.geometry.LinearUnitId;
import com.esri.arcgisruntime.geometry.Multipart;
import com.esri.arcgisruntime.geometry.Point;
import com.esri.arcgisruntime.geometry.PointCollection;
import com.esri.arcgisruntime.geometry.Polygon;
import com.esri.arcgisruntime.geometry.Polyline;
import com.esri.arcgisruntime.mapping.view.GraphicsOverlay;
import com.esri.arcgisruntime.mapping.view.MapView;
import com.esri.arcgisruntime.mapping.view.SketchCreationMode;
import com.esri.arcgisruntime.mapping.view.SketchEditor;
import com.esri.arcgisruntime.mapping.view.SketchStyle;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.maptool.R;
import com.maptool.adapter.ClipGeometryAdapter;
import com.maptool.callback.ApplicationCallBack;
import com.maptool.config.MapConfig;
import com.maptool.pojo.ClipPojo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;

/**
 * 图斑修整
 */
public class GeometryClip {

    private static GeometryClip instance;

    //使用单例避免静态便量内存泄漏风险
    public static GeometryClip getInstance() {
        if (instance == null) {
            instance = new GeometryClip();
        }
        return instance;
    }


    public SketchEditor sketchEditor;
    public SketchStyle sketchStyle;
    public GraphicsOverlay mHighlightGraphicsOverlay;
    public ApplicationCallBack.DataCallBack dataCallBack;
    private MapView mMapView;

    /**
     * @param mapView 地图
     * @param type    1、通过流状线修边；2、通过点状线修边;默认1-流状面
     */
    public void clip(MapView mapView, int type) throws Exception {
        mMapView = mapView;
        mHighlightGraphicsOverlay = new GraphicsOverlay();
        mapView.getGraphicsOverlays().add(mHighlightGraphicsOverlay);
        sketchEditor = mapView.getSketchEditor();
        if (sketchEditor == null) {
            sketchEditor = new SketchEditor();
        } else {
            sketchStyle = sketchEditor.getSketchStyle();
        }
        sketchEditor.setSketchStyle(MapConfig.getSketchStyle());
        mapView.setSketchEditor(sketchEditor);
        if (type == 1) {
            sketchEditor.start(SketchCreationMode.FREEHAND_LINE);
        } else {
            sketchEditor.start(SketchCreationMode.POLYLINE);
        }
    }

    /**
     * @param mapView  地图
     * @param geometry 图形
     * @param saveType 是否保留图形，如果修边修出多个图形后；
     *                 1:保留多图形中面积最大的图形，
     *                 2:原路返回，上层用户自己操作，
     *                 3:包中自动处理
     *                 4、有多个图形返回所有图形
     *                 默认1
     * @return
     * @throws Exception
     */
    public Geometry saveClipGeometry(Activity context, MapView mapView, Geometry geometry, int saveType, ApplicationCallBack.DataCallBack mDataCallBack) throws Exception {
        //获取修剪的线
        Polyline polyline = (Polyline) sketchEditor.getGeometry();
        if (saveType == 3) {
            dataCallBack = mDataCallBack;
        }
        //简化图形
        Geometry simplify = GeometryEngine.simplify(geometry);
        //修剪图形
        ImmutablePartCollection parts;
        Polygon reshapePolygon = null;
        Polyline reshapePolyline = null;
        if (simplify.getGeometryType() == GeometryType.POLYGON) {
            Multipart reshape = GeometryEngine.reshape((Polygon) simplify, polyline);
            reshapePolygon = (Polygon) reshape;
            if (saveType == 2) {
                return reshapePolygon;
            }
            parts = reshape.getParts();
        } else if (simplify.getGeometryType() == GeometryType.POLYLINE) {
            Multipart reshape = GeometryEngine.reshape((Polyline) simplify, polyline);
            reshapePolyline = (Polyline) reshape;
            if (saveType == 2) {
                return reshapePolyline;
            }
            parts = reshape.getParts();
        } else {
            throw new Exception("图形传入错误");
        }

        int size = parts.size();
        if (size > 1) {

            List<Double> list = new ArrayList<>();
            List<Geometry> geometryList = new ArrayList<>();
            List<ClipPojo> clipPojos = new ArrayList<>();
            ClipPojo clipPojo = null;
            for (ImmutablePart part : parts) {
                clipPojo = new ClipPojo();
                Iterable<Point> points = part.getPoints();
                PointCollection pointCollection = new PointCollection(mapView.getSpatialReference());
                for (Point point : points) {
                    pointCollection.add(point);
                }
                if (reshapePolygon != null) {
                    /**
                     * 面记录面积
                     */
                    Polygon polygon = new Polygon(pointCollection);
                    double geodetic = GeometryEngine.areaGeodetic(polygon, new AreaUnit(AreaUnitId.SQUARE_METERS), GeodeticCurveType.GREAT_ELLIPTIC);
                    list.add(geodetic);
                    geometryList.add(polygon);
                    clipPojo.setGeometry(polygon);
                } else {
                    /**
                     * 线记录长度
                     */
                    Polyline polyline1 = new Polyline(pointCollection);
                    double distance = GeometryEngine.lengthGeodetic(polyline1, new LinearUnit(LinearUnitId.METERS), GeodeticCurveType.GREAT_ELLIPTIC);
                    list.add(distance);
                    geometryList.add(polyline1);
                    clipPojo.setGeometry(polyline1);
                }
                clipPojo.setId(UUID.randomUUID().toString().replace("-", ""));
                clipPojos.add(clipPojo);
            }

            if (saveType == 1) {
                Double max = Collections.max(list);
                int i = list.indexOf(max);
                return geometryList.get(i);
            } else if (saveType == 4) {
                mDataCallBack.execute(geometryList);
            } else {
                dealGeometry(clipPojos, context);
            }
        } else {
            if (reshapePolygon != null) {
                return reshapePolygon;
            } else {
                return reshapePolyline;
            }
        }
        return null;
    }


    private BottomSheetDialog bottomSheetDialog;

    private void dealGeometry(List<ClipPojo> clipPojos, Activity context) {
        bottomSheetDialog = new BottomSheetDialog(context, R.style.BottomSheetDialog);
        LinearLayout bottomSheet = (LinearLayout) context.getLayoutInflater().inflate(R.layout.bottom, null);
        bottomSheetDialog.setContentView(bottomSheet);
        bottomSheetDialog.setCanceledOnTouchOutside(false);
        ListView clipListView = bottomSheet.findViewById(R.id.clipListView);
        ClipGeometryAdapter dkSaveAdapter = new ClipGeometryAdapter(context, clipPojos);
        clipListView.setAdapter(dkSaveAdapter);
        dkSaveAdapter.setLookApi(new LookApi());
        dkSaveAdapter.setSaveApi(new SaveApi());
        bottomSheetDialog.show();

        Button cancelBtn = bottomSheet.findViewById(R.id.cancelBtn);
        cancelBtn.setOnClickListener(v -> {
            MapConfig.clearGraphicsOverlay(mHighlightGraphicsOverlay);
            bottomSheetDialog.cancel();
        });
    }

    /**
     * 查看
     */
    private class LookApi implements ClipGeometryAdapter.LookApi {

        @Override
        public void lookFun(ClipPojo item) {
            MapConfig.clearGraphicsOverlay(mHighlightGraphicsOverlay);
            Geometry geometry = item.getGeometry();
            MapConfig.highlightGeometry(geometry, mHighlightGraphicsOverlay);
        }
    }

    /**
     * 保存
     */
    private class SaveApi implements ClipGeometryAdapter.SaveApi {

        @Override
        public void saveFun(ClipPojo item) {
            closeClip();
            bottomSheetDialog.dismiss();
            dataCallBack.execute(item);
        }
    }


    /**
     * 关闭修边
     */
    public void closeClip() {
        /**
         * 还原原来的样式
         */
        MapConfig.clearGraphicsOverlay(mHighlightGraphicsOverlay);
        if (sketchStyle != null) {
            sketchEditor.setSketchStyle(sketchStyle);
        }
        if (sketchEditor != null) {
            sketchEditor.stop();
        }
    }
}
